package com.hn658.base.message.frontend.interceptor;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.transport.http.AbstractHTTPDestination;
import org.springframework.beans.factory.annotation.Autowired;

import com.hn658.base.message.account.entity.AccountUserInfoEO;
import com.hn658.base.message.account.service.IAccountUserManagerService;
import com.hn658.base.message.common.enums.ServicesContants;
import com.hn658.base.message.common.exceptions.FilterException;
import com.hn658.base.message.frontend.context.CurrentUserContext;
import com.hn658.base.message.frontend.context.RequestContext;
import com.hn658.base.message.notisender.sender.comet.IIsOnlineManager;
import com.hn658.framework.common.interceptor.AbstractInterceptor;
import com.hn658.framework.logging.Logger;
import com.hn658.framework.logging.LoggerFactory;
import com.hn658.framework.logging.enums.LogCategory;
import com.hn658.framework.security.cryptography.HMAC;
import com.hn658.framework.security.cryptography.HexBinrary;
import com.hn658.framework.shared.utils.UUIDUtils;


/**
 * 初始化一些携带的请求参数
 * 
 * @ClassName: ContextInitInterceptor
 * @author ztjie
 * @date 2015年3月13日 下午3:10:19
 */
public class AuthContextInitInterceptor extends AbstractInterceptor {

	/**
	 * 日志输出
	 */
	private static final Logger logger = LoggerFactory
			.getLogger(AuthContextInitInterceptor.class);

	@Autowired
	private IAccountUserManagerService accountInfoService;
	
	@Autowired
	private IIsOnlineManager isOnlineManager;

	public AuthContextInitInterceptor() {
		super(Phase.RECEIVE);
	}

	@Override
	public void handle(Message message) {
		// 首先清空当前线程Session，
		// 因请求线程池原因，当前线程可能会残留上次访问数据
		CurrentUserContext.clean();

		// 获取当前的http请求对象
		HttpServletRequest request = (HttpServletRequest) message
				.get(AbstractHTTPDestination.HTTP_REQUEST);

		// 获取位于HTTP HEAD中的uid
		String uid = request.getHeader(ServicesContants.SERVICE_REQUEST_HEADER_UID);
		if (StringUtils.isEmpty(uid)) {
			uid = request.getParameter(ServicesContants.SERVICE_REQUEST_HEADER_UID);
		}

        logger.debug(LogCategory.SYSTEM, String.format("当前拦截请求的Uid为 %s", uid));
        if(StringUtils.isEmpty(uid)){
        	throw new FilterException(FilterException.NoUid);
        }
        // 获取位于HTTP HEAD中的appId
        String appId = request.getHeader(ServicesContants.SERVICE_REQUEST_HEADER_APPID);
        if (StringUtils.isEmpty(appId)) {
        	appId = request.getParameter(ServicesContants.SERVICE_REQUEST_HEADER_APPID);
 		}
        logger.debug(LogCategory.SYSTEM, String.format("当前拦截请求的AppId为 %s", appId));
        if(StringUtils.isEmpty(appId)){
        	throw new FilterException(FilterException.NoAppId);
        }
        // 获取位于HTTP HEAD中的token
        String authToken = request.getHeader(ServicesContants.SERVICE_REQUEST_HEADER_TOKEN);
        if (StringUtils.isEmpty(authToken)) {
        	authToken = request.getParameter(ServicesContants.SERVICE_REQUEST_HEADER_TOKEN);
        }
	    logger.debug(LogCategory.SYSTEM, String.format("当前拦截请求的authToken为 %s", authToken));
	    if(StringUtils.isEmpty(authToken)){
	    	throw new FilterException(FilterException.NoAuthKey);
	    }
        // 根据设备号对应token
        String token = accountInfoService.findUserToken(appId, uid);
        logger.debug(LogCategory.SYSTEM, String.format("服务端存储的token为%s", token));
        if(StringUtils.isEmpty(token)){
        	throw new FilterException(FilterException.NoToken);
        }
        //判断token是否正确 
        if(authToken.compareToIgnoreCase(token) != 0){
        	throw new FilterException(FilterException.InvalidToken);
        }
//        token=authToken;
        // 获取位于URL中的调用签名
        String sign = request.getHeader(ServicesContants.SERVICE_REQUEST_HEADER_SIGN);

        logger.debug(LogCategory.SYSTEM, String.format("当前拦截请求的sign为%s", sign));
        if(StringUtils.isEmpty(sign)){
        	throw new FilterException(FilterException.NoSign);
        }

        // 获取位于URL中的调用时间戳
        String timestamp = request.getHeader(ServicesContants.SERVICE_REQUEST_HEADER_TIMESTAMP);
        
        logger.debug(LogCategory.SYSTEM, String.format("当前拦截请求的timestamp为%s", timestamp));
        if(StringUtils.isEmpty(timestamp)){
        	throw new FilterException(FilterException.NoSign);
        }

        // 组装签名内容
        StringBuilder stringToEncrypt = new StringBuilder();
        stringToEncrypt.append("token").append(authToken);
        stringToEncrypt.append("appId").append(appId);
        stringToEncrypt.append("uid").append(uid);
        stringToEncrypt.append("timestamp").append(timestamp);

        logger.debug(LogCategory.SYSTEM,String.format("计算当前拦截请求的Signature Content为%s", stringToEncrypt));
        String encrypt = "";
        try {
            // 计算签名
        	byte[] hmaxByte = HMAC.encryptHMAC(stringToEncrypt.toString(), authToken);
            encrypt = HexBinrary.encodeHexBinrary(hmaxByte);
        } catch (IOException e) {
            logger.error(LogCategory.SYSTEM,String.format("JAX-RS服务调用出现异常:%s", ExceptionUtils.getStackTrace(e)));
            throw new FilterException("1013",FilterException.SignError);
        }

        logger.debug(LogCategory.SYSTEM,String.format("原始请求Sign为%s, 计算所得Sign为%s", sign, encrypt));
        // 验证签名与上传签名是否一致
        if(sign.compareToIgnoreCase(encrypt) != 0){
        	throw new FilterException("1013",FilterException.InValidSignature);
        }

		// 设置当前请求上下文信息
		RequestContext requestContext = new RequestContext();

		requestContext.setSign(sign);
		requestContext.setTimestamp(timestamp);
		requestContext.setToken(authToken);
		if (!StringUtils.isEmpty(uid)&&!StringUtils.isEmpty(appId)) {
			// 响应无用户id错误信息
			requestContext.setUid(Long.parseLong(uid));
			requestContext.setAppId(appId);
			AccountUserInfoEO loginUser = accountInfoService.findAccountByAppIdUid(appId, uid);
			// --只有第一次调用创建的时候才不会有用户
			if (loginUser != null) {
				requestContext.setUserInfo(loginUser);
			}
		}

		requestContext.setRequestId(UUIDUtils.getUUID());
		CurrentUserContext.setRequestContext(requestContext);
		
		// 设置用户在线状态
		isOnlineManager.online(appId,uid);
	}
}
